package com.duobaoyu.dby.supply.biz.converter;

import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.TypeReference;
import com.duobaoyu.dby.channel.adapter.enums.ChannelCodeEnum;
import com.duobaoyu.dby.channel.adapter.enums.biz.order.OrderExceptionTypeEnum;
import com.duobaoyu.dby.channel.boundary.bean.area.AddressInfoParam;
import com.duobaoyu.dby.channel.boundary.bean.area.ElectricityFeesInfoParam;
import com.duobaoyu.dby.channel.boundary.bean.order.param.*;
import com.duobaoyu.dby.channel.boundary.bean.order.result.*;
import com.duobaoyu.dby.common.core.constant.CommonConstants;
import com.duobaoyu.dby.common.core.constant.StringPool;
import com.duobaoyu.dby.common.core.convert.bean.ReferenceMapper;
import com.duobaoyu.dby.saas.product.common.base.json.SaleAttribute;
import com.duobaoyu.dby.supply.biz.client.boundary.order.bean.bo.*;
import com.duobaoyu.dby.supply.biz.client.product.bean.bo.SkuInfoCheckBO;
import com.duobaoyu.dby.supply.biz.enums.OrderRepairStatusEnum;
import com.duobaoyu.dby.supply.biz.enums.OrderTagEnum;
import com.duobaoyu.dby.supply.biz.util.ConverterUtils;
import com.duobaoyu.dby.supply.biz.util.CustomReferenceMapper;
import com.duobaoyu.dby.supply.common.biz.bo.area.ConsigneeInfo;
import com.duobaoyu.dby.supply.common.biz.bo.order.*;
import com.duobaoyu.dby.supply.common.biz.excel.OrderExportData;
import com.duobaoyu.dby.supply.common.biz.remote.dto.order.RecipientInfo;
import com.duobaoyu.dby.supply.common.biz.remote.to.order.OrderDetailTO;
import com.duobaoyu.dby.supply.common.biz.remote.to.order.OrderTO;
import com.duobaoyu.dby.supply.common.biz.vo.order.OrderRepairDetailVO;
import com.duobaoyu.dby.supply.common.biz.vo.order.OrderRepairPageVO;
import com.duobaoyu.dby.supply.db.entity.extend.OrderProductParamExtendInfo;
import com.duobaoyu.dby.supply.db.entity.extend.OrderProductResultExtendInfo;
import com.duobaoyu.dby.supply.db.entity.order.*;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.mapstruct.Builder;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单信息转换
 *
 * @author fengshaoyu
 * @version 1.0.0
 * @date 2023/10/7 13:59
 */
@Mapper(uses = {ReferenceMapper.class, CustomReferenceMapper.class},imports = {ConverterUtils.class, SaleAttribute.class, TypeReference.class,NumberUtil.class}, builder = @Builder(disableBuilder = true), componentModel = CommonConstants.COMPONENT_MODEL)
public interface OrderConverter {


	default OrderBO toOrder(Order order, List<OrderProduct> orderProductList, OrderConsignee orderConsignee, List<OrderLogistics> orderLogistics) {
		OrderBO orderBo = toOrder(order);
		if (Objects.isNull(orderBo)) {
			return null;
		}
		orderBo.setOrderAddress(toOrderAddress(orderConsignee));
		orderBo.setOrderProductList(this.toOrderProducts(orderProductList));
		orderBo.setOrderLogisticsList(toOrderLogisticsList(orderLogistics));
		return orderBo;
	}

	OrderBO toOrder(Order order);

	List<OrderBO> toOrders(List<Order> orderList);

	OrderInfoBO toOrderInfo(Order order);

	List<OrderInfoBO> toOrderInfoList(List<Order> orderList);

	@Mapping(target = "paramExtend", source = "paramExtend")
	@Mapping(target = "resultExtend", source = "resultExtend")
	@Mapping(target = "saleAttributes", expression = "java(ConverterUtils.toJsonString(orderProduct.getSaleAttributes()))")
	OrderProductBO toOrderProduct(OrderProduct orderProduct);

	List<OrderProductBO> toOrderProducts(List<OrderProduct> orderProduct);

	@Mapping(source = "addressDetail", target = "address")
	OrderAddressBO toOrderAddress(OrderConsignee orderConsignee);

	@Mapping(source = "address", target = "addressDetail")
	OrderConsignee toOrderAddress(OrderAddressBO orderAddress);

	@Mapping(target = "skuInfoParamList", expression = "java(buildSkuInfoParamList(order))")
	@Mapping(target = "addressInfoParam", source = "orderAddress")
	@Mapping(target = "recipientInfoParam", source = "orderAddress")
	OrderConfirmParam toOrderConfirmParam(OrderBO order);

	/**
	 * 通过OrderBO构建商品信息参数
	 * @param order
	 * @return
	 */
	default List<SkuInfoParam> buildSkuInfoParamList(OrderBO order){
		if(Objects.isNull(order) || Objects.isNull(order.getOrderProductList())) {
			return null;
		}
		ArrayList<SkuInfoParam> skuInfoParamList = Lists.newArrayList();
		for (OrderProductBO orderProduct : order.getOrderProductList()) {
			SkuInfoParam skuInfoParam = new SkuInfoParam();
			skuInfoParam.setProductType(orderProduct.getProductType());
			skuInfoParam.setSkuCode(orderProduct.getSkuCode());
			skuInfoParam.setChannelProductCode(orderProduct.getChannelProductCode());
			skuInfoParam.setChannelSkuCode(orderProduct.getChannelSkuCode());
			skuInfoParam.setChannelSpecId(orderProduct.getChannelSpecId());
			skuInfoParam.setChannelSkuName(orderProduct.getSkuName());
			skuInfoParam.setSkuNum(orderProduct.getSkuNum());
			skuInfoParam.setChannelSkuUnitPrice(orderProduct.getPlatformPrice());
			skuInfoParam.setRechargeAmount(orderProduct.getOriginalPrice());
			skuInfoParam.setChannelMarketPrice(orderProduct.getOriginalPrice());
			skuInfoParam.setChannelNakedPrice(orderProduct.getChannelNakedPrice());


			skuInfoParam.setSkuPayPrice(NumberUtil.mul(skuInfoParam.getSkuNum(),skuInfoParam.getChannelSkuUnitPrice()));
			skuInfoParam.setProductCode(orderProduct.getProductCode());
			skuInfoParam.setRechargeAccount(order.getRechargeAccount());
			// 扩展参数
			ExtendInfoParam extendInfoParam = toOrderProductExtendInfoParam(orderProduct.getParamExtend());
			skuInfoParam.setExtendInfoParam(extendInfoParam);
			skuInfoParamList.add(skuInfoParam);
		}
		return skuInfoParamList;
	}

	/**
	 * 订单商品扩展数据转换
	 */
	@Mapping(target = "skuIntervalPriceParamList", source = "tieredPrice")
	@Mapping(target = "mobileOperator", source = "phoneOperator.operatorType")
	@Mapping(target = "flowValue", source = "phoneOperator.flowValue")
	@Mapping(target = "electricityFeesParam", source = "electricityFees")
	ExtendInfoParam toOrderProductExtendInfoParam(OrderProductBO.OrderExtendParam orderProductExtendParam);

	/**
	 * 电费扩展参数转换
	 */
	@Mapping(target = "electricOperator", source = "operator")
	@Mapping(target = "electricProvinceCode", source = "provinceCode")
	@Mapping(target = "electricProvinceName", source = "provinceName")
	@Mapping(target = "electricCityCode", source = "cityCode")
	@Mapping(target = "electricCityName", source = "cityName")
	@Mapping(target = "electricCertificatesNo", source = "certificatesNo")
	@Mapping(target = "electricCertificatesType", source = "certificatesType")
	ExtendInfoParam.ElectricityFeesParam toElectricityFeesParam(OrderProductParamExtendInfo.ElectricityFees electricityFees);


	@Mapping(target = "addressDetail", source = "address")
	AddressInfoParam toAddressInfoParam(OrderAddressBO orderAddress);


	OrderConfirmResultBO.ConfirmSuccessBO toOrderConfirmSuccess(OrderConfirmResult orderConfirmResult);

	/**
	 * bo to to
	 *
	 * @param errorSkuInfoList bo
	 * @return OrderTO.ErrorSkuInfo to
	 */
	List<OrderTO.ErrorSkuInfo> toOrderErrorSkuInfoList(List<SkuInfoCheckBO.ErrorSkuInfo> errorSkuInfoList);


	/**
	 * 拆单结果
	 *
	 * @param orderSplitResult result
	 * @return OrderSplitBO bo
	 */
	OrderSplitBO.OrderSplitSkuInfo toOrderSplit(OrderSplitResult.OrderSplitSkuInfo orderSplitResult);


	List<OrderSplitBO.OrderSplitSkuInfo> toOrderSplit(List<OrderSplitResult.OrderSplitSkuInfo> orderSplitResult);

	OrderBO copy(OrderBO order);

	OrderDetailTO copy(OrderDetailTO order);

	Order toOrder(OrderBO newOrder);

	List<Order> toOrderList(List<OrderBO> newOrderList);

	@Mapping(source = "channelPayAmount", target = "channelPayAmount", ignore = true)
	OrderProductBO copyOrderProduct(OrderProductBO orderProduct);

	@Mapping(target = "saleAttributes", expression = "java(ConverterUtils.parseObject(orderProduct.getSaleAttributes(),new TypeReference<List<SaleAttribute>>(){}))")
	OrderProduct toOrderProduct(OrderProductBO orderProduct);

	List<OrderProduct> toOrderProductList(List<OrderProductBO> productList);

	/**
	 * 绑定订单地址
	 *
	 * @param consigneeInfo
	 * @return
	 */
	OrderConsignee toOrderConsignee(ConsigneeInfo consigneeInfo);


	ChannelOrderDetailOutBO toChannelOrderDetailOut(OrderInfoResult orderInfo);

	AddressInfoParam toAddressInfoParam(com.duobaoyu.dby.supply.common.biz.remote.dto.area.ConsigneeInfo consigneeInfo);

	List<OrderSubmitBO.OrderInfo> toSubmitOrderInfoList(List<OrderSubmitResult.OrderInfo> orderInfoList);

	List<OrderLogisticsBO> toOrderLogisticsList(List<OrderLogistics> orderLogistics);

	OrderDetailTO.OrderLogisticsTO toOrderLogistics(OrderLogisticsBO orderLogistics);

	List<OrderDetailTO> toOrderDetailList(List<OrderBO> orderList);

	@Mapping(target = "extendInfo.couponInfos", source = "resultExtend.couponInfos")
	OrderDetailTO.OrderProductTO toOrderProductTo(OrderProductBO orderProduct);

	List<OrderCancelParam> toCancelOrderParam(List<CancelOrderInBO> cancelOrderInList);

	RecipientInfoParam toRecipientInfoParam(RecipientInfo recipientInfo);

	OrderConfirmResultBO.ConfirmFailureBO toConfirmFailure(OrderConfirmResult orderConfirmResult);

	List<OrderRepair> toOrderRepairs(List<SaveOrderRepairBO> orderRepairList);

	ConsigneeInfo toOrderConsigneeInfo(AddressInfoParam addressInfoParam);

    List<OrderRepairPageVO> toOrderRepairPageList(List<OrderRepair> orderRepairs);

	AddressInfoParam toSubmitOrderAddressInfoParam(ConsigneeInfo consigneeInfo);

	RecipientInfoParam toSubmitOrderRecipientInfoParam(com.duobaoyu.dby.supply.common.biz.bo.order.RecipientInfo recipientInfo);

    OrderRepairBO toOrderRepair(OrderRepair orderRepair);

    List<OrderRepairBO> toOrderRepairList(List<OrderRepair> orderRepair);


	OrderRepairRecordBO toOrderRepairRecord(OrderRepairRecord orderRepairRecord);
    List<OrderRepairRecordBO> toOrderRepairRecordList(List<OrderRepairRecord> orderRepairRecordList);

    default OrderRepairDetailVO.OrderInfoVO toRepairOrderInfo(OrderRepairBO orderRepair, OrderBO order) {
        OrderRepairDetailVO.OrderInfoVO orderInfo = new OrderRepairDetailVO.OrderInfoVO();
        orderInfo.setOrderSn(order.getOrderSn());
        orderInfo.setSupplyTradeSn(order.getSupplyTradeSn());
        orderInfo.setBizTradeSn(order.getBizTradeSn());
        orderInfo.setChannelCode(order.getChannelCode());
        orderInfo.setChannelOrderAmount(order.getChannelOrderAmount());
        orderInfo.setChannelFreightAmount(order.getChannelFreightAmount());
        orderInfo.setOrderCreateTime(order.getCreateTime());
        orderInfo.setIsLargeAmountOrder(OrderTagEnum.isLargeAmountOrder(order.getOrderTag()));
		orderInfo.setChannelCodeMsg(Optional.ofNullable(ChannelCodeEnum.getChannelCodeEnumByCode(orderRepair.getChannelCode())).map(ChannelCodeEnum::getDescribe).orElse(StringPool.EMPTY));
        orderInfo.setExceptionType(orderRepair.getExceptionType());
        orderInfo.setExceptionTypeStr(OrderExceptionTypeEnum.getDescByType(orderRepair.getExceptionType()));
        orderInfo.setLastRepairTime(orderRepair.getLastRepairTime());
		orderInfo.setRepairStatus(orderRepair.getRepairStatus());
		orderInfo.setRepairStatusStr(OrderRepairStatusEnum.getDescByStatus(orderRepair.getRepairStatus()));
		orderInfo.setChannelTotalAmount(NumberUtil.add(order.getChannelOrderAmount(), order.getChannelFreightAmount()));
		orderInfo.setChannelTradeOrderSn(order.getChannelTradeOrderSn());
		orderInfo.setOrderType(order.getOrderType());
        return orderInfo;
    }

	@Mapping(target = "totalAmount", expression = "java(NumberUtil.mul(orderProduct.getSkuNum(), orderProduct.getPlatformPrice()))")
	OrderRepairDetailVO.OrderProductVO toOrderRepairDetailProduct(OrderProductBO orderProduct);

    List<OrderRepairDetailVO.OrderProductVO> toOrderRepairDetailProductList(List<OrderProductBO> orderProductList);

    OrderRepairDetailVO.OrderConsigneeVO toOrderRepairDetailConsignee(OrderAddressBO orderAddress);


	/*********************************导出转换***************************/
	@Mapping(target = "consigneeName", source = "recipientName")
	@Mapping(target = "consigneePhone", source = "recipientMobile")
	@Mapping(target = "consigneeProvinceName", source = "provinceName")
	@Mapping(target = "consigneeCityName", source = "cityName")
	@Mapping(target = "consigneeCountyName", source = "countyName")
	@Mapping(target = "consigneeTownName", source = "townName")
	@Mapping(target = "consigneeAddress", source = "addressDetail")
	@Mapping(target = "createTime", source = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
	@Mapping(target = "updateTime", source = "updateTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
	@Mapping(target = "saleAttributes", ignore = true)
	OrderExportData toOrderExport(OrderExportBO orderExport);


	default OrderConsignee toLargeOrderConsigneeBuild(OrderSplitBO.OrderSplitSkuInfo orderSplitSkuInfo, String orderSn, String supplyTradeSn){
		OrderConsignee orderConsignee = new OrderConsignee();
		if(ObjectUtils.isEmpty(orderSplitSkuInfo.getConsigneeInfo()) || ObjectUtils.isEmpty(orderSplitSkuInfo.getRecipientInfo())){
			return null;
		}
		orderConsignee.setOrderSn(orderSn);
		orderConsignee.setSupplyTradeSn(supplyTradeSn);
		orderConsignee.setProvinceCode(orderSplitSkuInfo.getConsigneeInfo().getProvinceCode());
		orderConsignee.setProvinceName(orderSplitSkuInfo.getConsigneeInfo().getProvinceName());
		orderConsignee.setCityCode(orderSplitSkuInfo.getConsigneeInfo().getCityCode());
		orderConsignee.setCityName(orderSplitSkuInfo.getConsigneeInfo().getCityName());
		orderConsignee.setCountyCode(orderSplitSkuInfo.getConsigneeInfo().getCountyCode());
		orderConsignee.setCountyName(orderSplitSkuInfo.getConsigneeInfo().getCountyName());
		orderConsignee.setTownCode(orderSplitSkuInfo.getConsigneeInfo().getTownCode());
		orderConsignee.setTownName(orderSplitSkuInfo.getConsigneeInfo().getTownName());
		orderConsignee.setAddressDetail(orderSplitSkuInfo.getConsigneeInfo().getAddressDetail());
		orderConsignee.setRecipientName(orderSplitSkuInfo.getRecipientInfo().getRecipientName());
		orderConsignee.setRecipientMobile(orderSplitSkuInfo.getRecipientInfo().getRecipientMobile());
		orderConsignee.setRecipientIdCardNum(orderSplitSkuInfo.getRecipientInfo().getRecipientIdCardNum());
		return orderConsignee;
	}

	@Mapping(target = "paramExtend", source = "orderProductParamExtendInfo")
	@Mapping(target = "saleAttributes", expression = "java(ConverterUtils.parseObject(orderSplitSkuInfo.getSaleAttributes(),new TypeReference<List<SaleAttribute>>(){}))")
	OrderProduct toOrderProduct(OrderSplitBO.SplitSkuInfo orderSplitSkuInfo);

	List<OrderProduct> toLargeOrderProduct(List<OrderSplitBO.SplitSkuInfo> skuInfoList);

	default OrderConsignee orderConsigneeBuild(OrderSubmitBO.OrderInfo orderInfo, String orderSn, String supplyTradeSn){
		OrderConsignee orderConsignee = new OrderConsignee();
		ConsigneeInfo consigneeInfo = orderInfo.getConsigneeInfo();
		com.duobaoyu.dby.supply.common.biz.bo.order.RecipientInfo recipientInfo = orderInfo.getRecipientInfo();
		if(ObjectUtils.isEmpty(orderInfo.getConsigneeInfo()) || ObjectUtils.isEmpty(orderInfo.getRecipientInfo())){
			return null;
		}

		orderConsignee.setOrderSn(orderSn);
		orderConsignee.setSupplyTradeSn(supplyTradeSn);
		orderConsignee.setProvinceCode(consigneeInfo.getProvinceCode());
		orderConsignee.setProvinceName(consigneeInfo.getProvinceName());
		orderConsignee.setCityCode(consigneeInfo.getCityCode());
		orderConsignee.setCityName(consigneeInfo.getCityName());
		orderConsignee.setCountyCode(consigneeInfo.getCountyCode());
		orderConsignee.setCountyName(consigneeInfo.getCountyName());
		orderConsignee.setTownCode(consigneeInfo.getTownCode());
		orderConsignee.setTownName(consigneeInfo.getTownName());
		orderConsignee.setAddressDetail(consigneeInfo.getAddressDetail());
		orderConsignee.setRecipientName(recipientInfo.getRecipientName());
		orderConsignee.setRecipientMobile(recipientInfo.getRecipientMobile());
		orderConsignee.setRecipientIdCardNum(recipientInfo.getRecipientIdCardNum());
		return orderConsignee;
	}

	@Mapping(source = "orderProductParamExtendInfo",target = "paramExtend")
	@Mapping(target = "saleAttributes", expression = "java(ConverterUtils.parseObject(skuInfo.getSaleAttributes(),new TypeReference<List<SaleAttribute>>(){}))")
	OrderProduct toOrderProduct(OrderSubmitBO.OrderInfo.SkuInfo skuInfo);

	List<OrderProduct> toOrderProduct(List<OrderSubmitBO.OrderInfo.SkuInfo> skuInfos);

	com.duobaoyu.dby.supply.common.biz.bo.order.RecipientInfo toRecipientInfo(RecipientInfoParam recipientInfoParam);

	com.duobaoyu.dby.supply.common.biz.bo.order.ElectricityFeesInfo toElectricityFeesInfo(ElectricityFeesInfoParam electricityFeesInfoParam);

	ElectricityFeesInfoParam toElectricityFeesInfoParam(com.duobaoyu.dby.supply.common.biz.remote.dto.order.ElectricityFeesInfo electricityFeesInfo);

	OrderProductParamExtendInfo.ElectricityFees toElectricityFees(com.duobaoyu.dby.supply.common.biz.remote.dto.order.ElectricityFeesInfo electricityFeesInfo);

	/**
	 * 卡券信息转换
	 * @param card
	 * @return
	 */
	@Mapping(source = "cardDeadline", target = "effectiveTime")
	@Mapping(source = "cardNumber", target = "cardNo")
	@Mapping(source = "linkUrl", target = "cardLink")
	OrderProductResultExtendInfo.CouponInfo toOrderProductResultCouponInfoExtendInfo(ChannelOrderDetailOutBO.VirtualOrderDetail.Card card);


	@Mapping(source = "cardDeadline", target = "effectiveTime")
	@Mapping(source = "cardNumber", target = "cardNo")
	@Mapping(source = "linkUrl", target = "cardLink")
	OrderProductBO.OrderProductResultExtendInfo.CouponInfo toOrderProductCouponExtendInfo(ChannelOrderDetailOutBO.VirtualOrderDetail.Card card);

	List<OrderProductBO.OrderProductResultExtendInfo.CouponInfo> toOrderProductCouponExtendInfoList(List<ChannelOrderDetailOutBO.VirtualOrderDetail.Card> cardList);

	OrderAddressBO copyOrderAddress(OrderAddressBO orderAddress);

	OrderDetailTO.OrderProductTO copyOrderProductTo(OrderDetailTO.OrderProductTO orderProduct);

	/**
	 * 订单运费计算入参转换
	 */
    default List<OrderFreightCalcParam> toOrderFreightCalcParam(List<OrderBO> orderList) {
		if (CollectionUtils.isEmpty(orderList)) {
			return Collections.emptyList();
		}

		return orderList.stream().map(order->{
			OrderFreightCalcParam orderFreightCalcParam = new OrderFreightCalcParam();
			orderFreightCalcParam.setOrderSn(order.getOrderSn());
			orderFreightCalcParam.setChannelCode(order.getChannelCode());
			orderFreightCalcParam.setAddressInfoParam(this.toAddressInfoParam(order.getOrderAddress()));
			List<OrderFreightCalcParam.SkuInfo> skuInfoList = Optional.ofNullable(order.getOrderProductList()).orElse(Collections.emptyList()).stream().map(orderProduct -> {
				OrderFreightCalcParam.SkuInfo skuInfo = new OrderFreightCalcParam.SkuInfo();
				skuInfo.setSkuCode(orderProduct.getSkuCode());
				skuInfo.setSkuNum(orderProduct.getSkuNum());
				skuInfo.setPlatformPrice(orderProduct.getPlatformPrice());
				skuInfo.setChannelSkuCode(orderProduct.getChannelSkuCode());
				skuInfo.setChannelSpecId(orderProduct.getChannelSpecId());
				skuInfo.setChannelProductCode(orderProduct.getChannelProductCode());
				return skuInfo;
			}).collect(Collectors.toList());
			orderFreightCalcParam.setSkuInfoList(skuInfoList);
			return orderFreightCalcParam;
		}).collect(Collectors.toList());
	}

	/**
	 * 订单运费结果转换
	 */
	List<BatchCalcOrderFreightResultBO.OrderFreight> toOrderFreightList(List<OrderFreightCalcResult> orderFreightCalcResults);

	/**
	 * 订单运费结果转换
	 */
	@Mapping(target = "freightAmount", source = "channelFreightAmount")
	BatchCalcOrderFreightResultBO.OrderFreight toOrderFreight(OrderFreightCalcResult orderFreightCalcResult);

}
